/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.karol.lx.grader;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.karol.lx.model.GradeRequest;

/**
 * Pekerja asinkron grader. Mengirimkan request ke mesin eksekusi dengan HTTP
 * dan menerima hasilnya.
 *
 * @author karol
 */
public class GraderBackgroundWorker implements Runnable {

    public static final int MAX_REQUEUE = 10;
    private GradeRequest mRequest;
    private HttpClient mClient;
    private HttpContext mContext;
    private GraderEventListener mListener = null;
    private String mGraderUrl;

    public GraderBackgroundWorker(String pTargetUrl, GraderEventListener pListener, GradeRequest mRequest) {
        mGraderUrl = pTargetUrl;
        mListener = pListener;
        this.mRequest = mRequest;
        mClient = new DefaultHttpClient();
        mContext = new BasicHttpContext();
    }

    protected final void notifyGradingSuccess() {
        if (mListener != null) {
            mListener.onGradingSuccess(mRequest);
        }
    }

    protected final void notifyGradingFailed(Object pReason, boolean disposable) {
        if (mListener != null) {
            mListener.onGradingFailed(mRequest, pReason, disposable);
        }
    }

    @Override
    public void run() {
        HttpPost tMethod = new HttpPost(mGraderUrl + "?id=" + mRequest.id);
        //HttpParams tParam = new BasicHttpParams();
        //tParam.setIntParameter("id", mRequest.id);
        //tMethod.setParams(tParam);
        try {
            HttpResponse tResponse = mClient.execute(tMethod, mContext);
            HttpEntity tEntity = tResponse.getEntity();

            //System.out.println(EntityUtils.toString(tEntity));
            if (tResponse.getStatusLine().getStatusCode() == 200) { //Success
                notifyGradingSuccess();
            } else if (tResponse.getStatusLine().getStatusCode() == 412) { //Failed, broken request, not requeued
                notifyGradingFailed("HTTP request broken", true);
            } else if (mRequest.getRequeueCount() >= MAX_REQUEUE) { //Repetitively requeued
                notifyGradingFailed("Maximum requeue reached", true);
            } else { //Try requeue, eventually removed by monitor
                notifyGradingFailed("HTTP response", false);
            }
        } catch (IOException ex) { //Failed, connection failure, possible machine down, requeued
            Logger.getLogger(GraderBackgroundWorker.class.getName()).log(Level.SEVERE, null, ex);
            notifyGradingFailed(ex, false);
        }
    }
}
